package tests.game;

import static org.junit.Assert.*;
import java.util.Vector;

import game.Run;
import game.Tile;
import game.Tile.TileColor;
import game.exceptions.RunException;
import game.exceptions.SetException;
import game.exceptions.TileException;

import org.junit.Before;
import org.junit.Test;

public class RunTest {

	private TileColor _color;
	private Vector<Tile> _tiles = new Vector<Tile>();
	
	@Before
	public void setUp() throws Exception {
		_color = TileColor.BLUE;
		_tiles.add(new Tile(5,_color));
		_tiles.add(new Tile(6,_color));
		_tiles.add(new Tile(7,_color));
	}

	@Test
	public void testRun() {
		
		try {
			//Creating correct run.
			try {
				new Run(_color, _tiles);
			}catch (RunException e) {
				fail("Run Exception was thrown while creating correct Run.");
			} catch (SetException e) {
				fail("Set Exception was thrown while creating correct Run.");
			}
			
			//Creating run with less that 3 tiles.
			_tiles.remove(0);
			try {
				new Run(_color, _tiles);
				fail("Run was created with less than 3 tiles.");
			}catch (RunException e) {
				fail("Run exception was thrown insted of Set exception while creating Ru with less than 3 tiles.");
			} catch (SetException e) {
				System.out.println(e.getMessage());
			} 
			
			//Creating run with non-sequential tiles.
			_tiles.add(new Tile(9,_color));
			try {
				new Run(_color, _tiles);
				fail("Run was created with non sequential tiles.");
			}catch (RunException e) {
				System.out.println(e.getMessage());
			} catch (SetException e) {
				fail("Set exception was thrown insted of Run exception while creating Run with non sequential tiles.");
			} 
			
			//Creating run with tile from different colors.
			_tiles.remove(new Tile(9,_color));
			_tiles.add(new Tile(8,TileColor.BLACK));
			try {
				new Run(_color, _tiles);
				fail("Run was created with tiles from different colors.");
			}catch (RunException e) {
				System.out.println(e.getMessage());
			} catch (SetException e) {
				fail("Set exception was thrown insted of Run exception while creating Run with tiles from different.");
			} 
			
		} catch (TileException e) {
			fail("Tile exception was thrown during Run constructors test." +
				 "Exception Message is: " + e.getMessage());
		}
	}
	
	@Test
	public void testAddTile() {
		try {
			Run tRun = new Run(_color,_tiles);
			
			//Test adding tile at the start of the run.
			try {
				tRun.addTile(new Tile(4,_color));
				assertTrue("The run not contains the added tile.",tRun.contains(new Tile(4,_color)));
			} catch (RunException e) {
				fail("Run exception was thrown while adding Tile at the start of the run.");
			}
			
			//Test adding tile at the end of the run.
			try {
				tRun.addTile(new Tile(8,_color));
				assertTrue("The run not contains the added tile.",tRun.contains(new Tile(8,_color)));
			} catch (RunException e) {
				fail("Run exception was thrown while adding Tile at the end of the run.");
			}
			
			//Test adding non sequential tile.
			try {
				tRun.addTile(new Tile(10,_color));
				fail("Run exception wasn't thrown while adding non sequential Tile to the run.");
			} catch (RunException e) {
				System.out.println(e.getMessage());
			}
			assertTrue("The run not contains the added tile.",!tRun.contains(new Tile(10,_color)));
		
			//Test adding tile with different color.
			try {
				tRun.addTile(new Tile(9, TileColor.BLACK));
				fail("Run exception wasn't thrown while adding Tile with different color to the run.");
			} catch (RunException e) {
				System.out.println(e.getMessage());
			}
			assertTrue("The run not contains the added tile.",!tRun.contains(new Tile(9, TileColor.BLACK)));
		} catch (RunException e) {
			fail("Set exception was thrown while testing addTile to Run.");
		} catch (SetException e) {
			fail("Set exception was thrown while testing addTile to Run.");
		} catch (TileException e) {
			fail("Tile exception was thrown while testing addTile to Run.");
		}
	}

	@Test
	public void testRemoveTile() {
		try {
			_tiles.add(new Tile(8, _color));
			_tiles.add(new Tile(9, _color));
			_tiles.add(new Tile(10, _color));
			Run tRun = new Run(_color, _tiles);
			
			//Remove tile from the start of the run.
			try {
				tRun.removeTile(new Tile(5,_color));
				assertTrue("Removed Tile still in the run.", !tRun.contains(new Tile(5, _color)));
			} catch (SetException e) {
				fail("Exception was thrown while removing a tile from start of a run.");
			}
			
			//Remove tile from the end of the run.
			try {
				tRun.removeTile(new Tile(10,_color));
				assertTrue("Removed Tile still in the run.", !tRun.contains(new Tile(10, _color)));
			} catch (SetException e) {
				fail("Exception was thrown while removing a tile from end of the run.");
			}
			
			//Remove tile from the middle of the run.
			try {
				tRun.removeTile(new Tile(7,_color));
				fail("Exception wasn't thrown while removing a tile from middle of a run.");
			} catch (SetException e) {
				System.out.println(e.getMessage());
			}
			assertTrue("Tile was removed while trying to remove it from the middle of the run.", tRun.contains(new Tile(7, _color)));
			
		} catch (RunException e) {
			fail("Set exception was thrown while testing removeTile from Run.");
		} catch (TileException e) {
			fail("Tile exception was thrown while testing removeTile from Run.");
		} catch (SetException e) {
			fail("Set exception was thrown while testing removeTile from Run.");
		}
	}

}
